package org.easySpace.common.aop;

import cn.hutool.core.util.IdUtil;
import org.easySpace.common.enums.Constants;
import org.easySpace.common.util.RequestUtil;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author lzh@aginome.com
 * @description 给自定义注解实现功能
 * @date 2022/07/15
 **/

@Aspect
@Component
@Slf4j
public class ControllerPrintAspect {

    @Value("${logging.logPrintSymbol:false}")
    private Boolean logPrintSymbol;

    private static final String TRACE_ID = "traceId";

    //声明切点
    @Pointcut("@annotation(org.easySpace.common.aop.ControllerPrint)")
    public void logPrint() {
    }

    @Around("logPrint()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws  Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        log.info("接口耗时: {}ms", System.currentTimeMillis() - startTime);
        MDC.remove(TRACE_ID);
        return result;
    }

    @Before("logPrint()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        MDC.put(TRACE_ID, IdUtil.fastSimpleUUID());
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.info("请求IP:{}", RequestUtil.getRemoteHost(request));
        log.info("请求路径:{}", request.getRequestURI());
        log.info("请求方式:{}", request.getMethod());
        String bodyJson = new Gson().toJson(joinPoint.getArgs());
        if(bodyJson.length() > Constants.LOG_LIMIT_LENGTH && !logPrintSymbol){
            log.info("body参数过长，长度为{}, 为避免oom不打印日志", bodyJson.length());
        } else {
            log.info("body参数:{}", bodyJson);
        }
    }


    @After("logPrint()")
    public void doAfter() {
    }


}
